import { ContextScene } from "./scene";
import { getRandomId } from "./utils";

/**
 * 上下文基类
 */
export class BaseContext<
    S extends Record<
        string,
        new (...args: unknown[]) => ContextScene<NonNullable<null>, NonNullable<null>>
    >
> {
    protected _id: string = getRandomId();
    /** 唯一标识 */
    get id() {
        return this._id;
    }
    /** 场景原型 */
    protected sceneProto: S;
    /** 场景 */
    protected scenes: Record<string, InstanceType<S[keyof S]>> = {};

    /**
     * @param sceneProto 场景原型
     */
    constructor(sceneProto: S) {
        this.sceneProto = sceneProto;
    }

    /**
     * 根据 key 和 type 获取场景，如果不存在则抛出异常
     * @param key 场景的键名
     * @param type 场景的类名
     * @returns 场景实例
     */
    getScene<K extends keyof S>(key: string, type: K): InstanceType<S[K]> {
        const scene = this.tryGetScene(key, type);
        if (!scene) {
            throw new Error(`Scene ${key} not found`);
        }
        return scene;
    }
    /**
     * 尝试根据 key 和 type 获取场景，如果不存在则返回 undefined
     * @param key 场景的键名
     * @param type 场景的类名
     * @returns 场景实例或 undefined
     */
    tryGetScene<K extends keyof S>(key: string, type: K): InstanceType<S[K]> | undefined {
        const scene = this.scenes[key];
        const SceneClass = this.sceneProto[type];
        if (scene && scene instanceof SceneClass) {
            return scene as InstanceType<S[K]>;
        }
        return undefined;
    }
    /**
     * 创建场景
     * @param key 场景的键名
     * @param type 场景的类名
     * @param config 场景的配置
     * @returns 场景实例
     */
    createScene<K extends keyof S>(
        key: string,
        type: K,
        config: ConstructorParameters<S[K]>
    ): InstanceType<S[K]> {
        if (this.scenes[key]) {
            throw new Error(`Scene ${key} already exists`);
        }
        const SceneClass = this.sceneProto[type];
        const scene = new SceneClass(...config) as InstanceType<S[K]>;
        this.scenes[key] = scene;
        return scene;
    }
}
